﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using Common.Utilities;
using Common.Utilities.Dispatcher;

namespace Workflows.Components.TextMining.Collapse
{
    /// <summary>
    /// 
    /// </summary>
    [Serializable]
    public class MergeCollapseInstruction:InstructionBase
    {
        #region props
        private string _ConnStr;
        /// <summary></summary>
        public string ConnStr
        {
            get
            {
                return this._ConnStr;
            }
            set
            {
                this._ConnStr = value;
            }
        }

        private string _SchemaName;
        /// <summary></summary>
        public string SchemaName
        {
            get
            {
                return this._SchemaName;
            }
            set
            {
                this._SchemaName = value;
            }
        }

        private string _CollapseOutputTablePrefix;
        /// <summary></summary>
        public string CollapseOutputTablePrefix
        {
            get
            {
                return this._CollapseOutputTablePrefix;
            }
            set
            {
                this._CollapseOutputTablePrefix = value;
            }
        }

        private string _CollapseMappingTablePrefix;
        /// <summary></summary>
        public string CollapseMappingTablePrefix
        {
            get
            {
                return this._CollapseMappingTablePrefix;
            }
            set
            {
                this._CollapseMappingTablePrefix = value;
            }
        }

        private int _PartFrom;
        /// <summary></summary>
        public int PartFrom
        {
            get
            {
                return this._PartFrom;
            }
            set
            {
                this._PartFrom = value;
            }
        }

        private int _PartTo;
        /// <summary></summary>
        public int PartTo
        {
            get
            {
                return this._PartTo;
            }
            set
            {
                this._PartTo = value;
            }
        }

        private string _IDField;
        /// <summary></summary>
        public string IDField
        {
            get
            {
                return this._IDField;
            }
            set
            {
                this._IDField = value;
            }
        }

        private List<string> _DescFields;
        /// <summary></summary>
        public List<string> DescFields
        {
            get
            {
                return this._DescFields;
            }
            set
            {
                this._DescFields = value;
            }
        }

        private string _CollapseIDField;
        /// <summary></summary>
        public string CollapseIDField
        {
            get
            {
                return this._CollapseIDField;
            }
            set
            {
                this._CollapseIDField = value;
            }
        }

        private string _ScoreField;
        /// <summary></summary>
        public string ScoreField
        {
            get
            {
                return this._ScoreField;
            }
            set
            {
                this._ScoreField = value;
            }
        }

        private string _MergeTableName;
        /// <summary></summary>
        public string MergeTableName
        {
            get
            {
                return this._MergeTableName;
            }
            set
            {
                this._MergeTableName = value;
            }
        }

        private string _MergeProfileFieldName;
        /// <summary></summary>
        public string MergeProfileFieldName
        {
            get
            {
                return this._MergeProfileFieldName;
            }
            set
            {
                this._MergeProfileFieldName = value;
            }
        }
        #endregion

        #region ctor
        /// <summary>
        /// 
        /// </summary>
        public MergeCollapseInstruction():base(Guid.Empty,Guid.Empty)
        {
            this._ConnStr = string.Empty;
            this._SchemaName = string.Empty;
            this._CollapseOutputTablePrefix = string.Empty;
            this._CollapseMappingTablePrefix = string.Empty;
            this._PartFrom = 1;
            this._PartTo = 1;
            this._IDField = string.Empty;
            this._DescFields=new List<string>();
            this._CollapseIDField = string.Empty;
            this._ScoreField = string.Empty;
            this._MergeTableName = string.Empty;
            this._MergeProfileFieldName = string.Empty;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="componentID"></param>
        /// <param name="jobTicketID"></param>
        /// <param name="connStr"></param>
        /// <param name="schemaName"></param>
        /// <param name="collapseOutputPrefix"></param>
        /// <param name="collapseMappingPrefix"></param>
        /// <param name="fromPart"></param>
        /// <param name="toPart"></param>
        /// <param name="idField"></param>
        /// <param name="collapseIDField"></param>
        /// <param name="scoreField"></param>
        /// <param name="descFields"></param>
        /// <param name="mergeTbl"></param>
        /// <param name="mergeProfileField"></param>
        public MergeCollapseInstruction(Guid componentID, Guid jobTicketID,
            string connStr, string schemaName, 
            string collapseOutputPrefix, string collapseMappingPrefix,
            int fromPart, int toPart,
            string idField, string collapseIDField, string scoreField,
            List<string> descFields,
            string mergeTbl, string mergeProfileField) 
            : base(componentID, jobTicketID)
        {
            this._ConnStr = connStr;
            this._SchemaName = schemaName;
            this._CollapseOutputTablePrefix = collapseOutputPrefix;
            this._CollapseMappingTablePrefix = collapseMappingPrefix;
            this._PartFrom = fromPart;
            this._PartTo = toPart;
            this._IDField = idField;
            this._DescFields = descFields;
            this._CollapseIDField = collapseIDField;
            this._ScoreField = scoreField;
            this._MergeTableName = mergeTbl;
            this._MergeProfileFieldName = mergeProfileField;
        }
        #endregion

        #region Overrides of InstructionBase

        /// <summary>
        /// serialize settings to xml
        /// the function below is mainly for storing into database as serialized form instead of string
        /// </summary>
        public override XmlNode Serialize(ref XmlDocument xDoc, ref XmlNode parentNode)
        {
            XmlNode xNode = XmlDataUtil.AddElement(ref xDoc, parentNode, "Instruction");
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "Type", this.GetType().FullName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ComponentID", this.OwnerComponentID.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "WorkerID", this.OwnerWorkerInstanceID.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SubmitTime", this.SubmitTime.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "StartTime", this.StartTime.ToString());

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ConnStr",this.ConnStr);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SchemaName", this.SchemaName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "CollapseOutputPrefix", this.CollapseOutputTablePrefix);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "CollapseMappingPrefix", this.CollapseMappingTablePrefix);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "FromPart", this.PartFrom.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ToPart", this.PartTo.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "IDField", this.IDField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "CollapseIDField", this.CollapseIDField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ScoreField", this.ScoreField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "MergeTable", this.MergeTableName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "MergeProfileIDField", this.MergeProfileFieldName);
            XmlNode descNodes = XmlDataUtil.AddElement(ref xDoc, xNode, "DescFields");
            if(this.DescFields !=null && this.DescFields.Count>0)
            {
                foreach(string descField in this.DescFields)
                {
                    XmlNode descNode = XmlDataUtil.AddElement(ref xDoc, descNodes, "DescField");
                    XmlDataUtil.UpdateAttribute(ref xDoc, descNode,"FieldName",descField);
                }
            }

            return xNode;
        }

        /// <summary>
        /// instantiated from xml
        /// "&lt;Instructions&gt;&lt;Instruction&gt;&lt;/Instruction&gt;&lt;/Instruction&gt;", must
        /// instantiate from first child of root node
        /// </summary>
        public override InstructionBase Instantiate(XmlNode xNode)
        {
            if (xNode.Attributes.GetNamedItem("Type").Value == this.GetType().FullName)
            {
                MergeCollapseInstruction instruction = new MergeCollapseInstruction();
                instruction.OwnerComponentID = new Guid(xNode.Attributes.GetNamedItem("ComponentID").Value);
                instruction.OwnerWorkerInstanceID = new Guid(xNode.Attributes.GetNamedItem("WorkerID").Value);
                instruction.SubmitTime = DateTime.Parse(xNode.Attributes.GetNamedItem("SubmitTime").Value);
                instruction.StartTime = DateTime.Parse(xNode.Attributes.GetNamedItem("StartTime").Value);

                instruction.ConnStr = XmlDataUtil.GetAttributeValue(xNode, "ConnStr", "");
                instruction.SchemaName = XmlDataUtil.GetAttributeValue(xNode, "SchemaName", "");
                instruction.CollapseOutputTablePrefix = XmlDataUtil.GetAttributeValue(xNode, "CollapseOutputPrefix", "");
                instruction.CollapseMappingTablePrefix = XmlDataUtil.GetAttributeValue(xNode, "CollapseMappingPrefix",
                                                                                       "");
                instruction.PartFrom = int.Parse(XmlDataUtil.GetAttributeValue(xNode, "FromPart", "1"));
                instruction.PartTo = int.Parse(XmlDataUtil.GetAttributeValue(xNode, "ToPart", "1"));
                instruction.IDField = XmlDataUtil.GetAttributeValue(xNode, "IDField", "");
                instruction.CollapseIDField = XmlDataUtil.GetAttributeValue(xNode, "CollapseIDField", "");
                instruction.ScoreField = XmlDataUtil.GetAttributeValue(xNode, "ScoreField", "");
                instruction.MergeTableName = XmlDataUtil.GetAttributeValue(xNode, "MergeTable", "");
                instruction.MergeProfileFieldName = XmlDataUtil.GetAttributeValue(xNode, "MergeProfileIDField", "");
                instruction.DescFields=new List<string>();
                XmlNodeList descNodes = xNode.SelectNodes("DescFields/DescField");
                if(descNodes !=null && descNodes.Count>0)
                {
                    foreach(XmlNode descNode in descNodes)
                    {
                        string fieldName = XmlDataUtil.GetAttributeValue(descNode, "FieldName", "");
                        instruction.DescFields.Add(fieldName);
                    }
                }

                return instruction;
            }
            else
            {
                throw new Exception("Unable to instantiate instruction: invalid type specified in xml node");
            }
        }

        #endregion
    }
}
